声明式事务

MySQL事务

Spring和MyBatis整合之后,默认会关闭事务,开启自动提交。因此事务需要手动打开。

一个使用 MyBatis-Spring 的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中。而不是给 MyBatis 创建一个新的专用事务管理器,MyBatis-Spring 借助了 Spring 中的 DataSourceTransactionManager 来实现事务管理。

一旦配置好了 Spring 的事务管理器,你就可以在 Spring 中按你平时的方式来配置事务。并且支持 @Transactional 注解和 AOP 风格的配置。在事务处理期间,一个单独的 SqlSession 对象将会被创建和使用。当事务完成时,这个 session 会以合适的方式提交或回滚。

  • 声明式事务:AOP
  • 编程式事务:需要在代码中,进行事务的管理。

1. 使用方法

这里直接在与MyBatis整合的第二种方式上进行修改。

详见这里

  1. mybatis配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <!--configuration核心配置文件-->
    <configuration>
        <typeAliases>
            <typeAlias type="org.gs.pojo.User" alias="user"/>
        </typeAliases>
        <mappers>
            <mapper resource="org/gs/mapper/UserMapper.xml" />
        </mappers>
    </configuration>
    
  2. spring配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/tx
            https://www.springframework.org/schema/tx/spring-tx.xsd">
    
        <!--从db.properties获取db配置信息-->
        <context:property-placeholder location="db.properties"/>
        <!--将db配置信息配置到spring的数据源中-->
        <!-- 这里也可以选择其他数据源,如 c3p0 dbcp druid-->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </bean>
    
        <!--配置SqlSessionFactory-->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!--将数据源内容注入-->
            <property name="dataSource" ref="dataSource"/>
            <!--可以携带mybatis原有的配置文件,一般用来指定别名-->
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
            <!--此处也可以映射文件-->
            <!--其实mybatis配置文件中的配置都可以在这里完成-->
            <!--<property name="mapperLocations" value="classpath:org/gs/mapper/UserMapper.xml"/>-->
        </bean>
    
        <!--配置mapper实现类,注入SqlSession-->
        <bean id="userMapper" class="org.gs.mapper.UserMapperImpl">
            <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
        </bean>
    
        <!--要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager 对象-->
        <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <constructor-arg name="dataSource" ref="dataSource"/>
        </bean>
    
        <!--配置事务的切面-->
        <tx:advice id="interceptor" transaction-manager="dataSourceTransactionManager">
            <!--给哪些方法配置事务-->
            <tx:attributes>
                <tx:method name="add"/>
                <tx:method name="update" propagation="REQUIRED"/>
                <tx:method name="query" read-only="true"/>
                <!--可以使用通配符-->
                <!--<tx:method name="*" propagation="REQUIRED"/>-->
            </tx:attributes>
        </tx:advice>
    
        <aop:config>
            <aop:pointcut id="pointcut" expression="execution(* org.gs.mapper.*.*(..))"/>
            <aop:advisor advice-ref="interceptor" pointcut-ref="pointcut"/>
        </aop:config>
    
    </beans>
    

完成以上步骤,就可以通过Spring给对应的mapper上指定的方法织入事务。

2. 相关属性

2.1. 配置事务的传播特性 propagation

  • REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。(默认)
  • SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
  • MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
  • REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
  • NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  • NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
  • NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。

3. 注意点

  1. @Transactional只能回滚RuntimeException以及其下子类抛出的异常,而不能回滚Exception抛出的异常。
  2. 如果需要支持回滚Exception异常需要加@Transactional(rollbackFor = Exception.class),建议添加。
  3. 如果方法不是public所修饰,则不会对Bean进行代理对象的创建以及代理方法的调用。
  4. Spring的事务通过代理对象来调用并提交/回滚。通过对类内部的方法调用并没有走代理方法调用,最终导致事务失效。
Copyright © rootwhois.cn 2021-2022 all right reserved,powered by GitbookFile Modify: 2023-03-05 10:55:52

results matching ""

    No results matching ""